open Uav_data
open Target
open Planning

module type Param = sig
  val init: unit -> planning_t
  val shaking: planning_t -> int -> (int list) * planning_t 
  val local_search: (int list) * planning_t -> planning_t list
  type eval_t
  val cost: planning_t -> eval_t
  val cmp: eval_t -> eval_t -> bool
  val print: planning_t -> unit
end

module Make(P : Param) = struct
  open P
  let start = fun goal_type ball video time ->
    let best_planning = ref (init ()) in
    let best_planning_cost = ref (cost !best_planning) in
   
    let planning = ref (!best_planning) in
    let planning_cost = ref (!best_planning_cost) in

     let nb_iter = ref 0 in
    while true do
      incr nb_iter;
      let neighborhood = 
	  (local_search (shaking !planning !nb_iter)) in
      if List.length neighborhood > 0 then
	begin
	  planning := List.hd neighborhood;
	  planning_cost := cost !planning;
	  for i=0 to List.length neighborhood -1 do
	    let ngbhd = List.nth neighborhood i in
	    let c = cost ngbhd in
	    if cmp c !best_planning_cost
	    then
	      begin
		best_planning_cost := c;
		planning_cost := c;
		best_planning := ngbhd;
		planning := ngbhd;
		print !planning;
	      end
	    else if cmp c !planning_cost 
	    then begin
	      planning_cost := c;
	      planning := ngbhd;
	    end
	  done;
	end
    done

end
